package com.example.ui_test.widget

import android.animation.Animator
import android.animation.ValueAnimator
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.os.Build
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View
import androidx.annotation.RequiresApi


/**
 *
 *
 * @Author: BigWhite
 * @CreateDate: 2021/4/27 14:41
 */
class MenuView(context: Context) : View(context) {
    private  var paint = Paint()
    private var path = Path()
    private var radius = 70f

    private  var mHeight = 0
    private  var mWidth = 0

    /**
     * 底部按钮＋的
     */
    private var pathMainIcon = Path()
    private var paintMainIcon = Paint()

    /**
     * 旋转角度
     */
    private  var rotate = 0f

    /**
     * 是否是开启状态
     */
    private  var isOpen = false

    /**
     * 是否在动画中
     */
    private var isAnimaling = false

    /**
     * 最大距离
     */
    private var distance = 300f

    /**
     * 辅助线
     */
    private var pathLine = Path()
    private var paintLine = Paint()

    private var listChildMenuPath = arrayListOf(Path(), Path(), Path())
    private var firstMenuOffset = 45f
    private  var menuSpace = 45f

    init {
        paint.color = Color.parseColor("#775587F2")
        paint.strokeWidth = 8f
        paint.style = Paint.Style.FILL

        paintMainIcon.color = Color.WHITE
        paintMainIcon.strokeWidth = 8f
        paintMainIcon.style = Paint.Style.STROKE

        paintLine.color = Color.LTGRAY
        paintLine.strokeWidth = 2f
        paintLine.style = Paint.Style.STROKE
    }

    constructor(context: Context, attrs: AttributeSet) : this(context) {}

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
        mHeight = measuredHeight
        mWidth = measuredWidth

        path.addArc(
            mWidth / 2 - radius,
            measuredHeight - 2 * radius,
            mWidth / 2 + radius,
            mHeight.toFloat(),
            0f,
            359f
        )
        path.close()

        pathMainIcon.moveTo(mWidth / 2 - radius * 2 / 3, measuredHeight - radius)
        pathMainIcon.lineTo(mWidth / 2 + radius * 2 / 3, measuredHeight - radius)
        pathMainIcon.moveTo(mWidth / 2f, measuredHeight - 5 * radius / 3)
        pathMainIcon.lineTo(mWidth / 2f, measuredHeight - radius / 3)

        calculatePath(0f)
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun onDraw(canvas: Canvas?) {
        super.onDraw(canvas)

        canvas?.drawArc(
            mWidth / 2 - radius,
            measuredHeight - 2 * radius,
            mWidth / 2 + radius,
            mHeight.toFloat(),
            0f,
            360f,
            true,
            paint
        )

        for (path in listChildMenuPath) {
            canvas?.drawPath(path, paint)
        }

        canvas?.rotate(rotate, mWidth / 2f, measuredHeight - radius)
        canvas?.drawPath(pathMainIcon, paintMainIcon)

        canvas?.rotate(-rotate, mWidth / 2f, measuredHeight - radius)
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    private fun calculatePath(scale: Float) {

        pathLine.reset()
        pathLine.addArc(
            mWidth / 2 - distance * scale,
            measuredHeight - radius - distance * scale,
            mWidth / 2 + distance * scale,
            mHeight.toFloat() - radius + distance * scale,
            -90f - firstMenuOffset,
            359f
        )
        pathLine.close()

        val pathMeasure = PathMeasure(pathLine, true)

        val p = 360 / menuSpace
        for (i in listChildMenuPath.indices) {
            val pathMenu = listChildMenuPath[i]
            pathMenu.reset()
            val pos = floatArrayOf(0f, 0f)
            pathMeasure.getPosTan(pathMeasure.length / p * i, pos, null)
            pathMenu.addArc(
                pos[0] - radius * scale,
                pos[1] - radius * scale,
                pos[0] + radius * scale,
                pos[1] + radius * scale,
                0f,
                359f
            )
            pathMenu.close()
        }
    }

    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    @SuppressLint("ClickableViewAccessibility")
    override fun onTouchEvent(event: MotionEvent?): Boolean {

        when(event?.action){
            MotionEvent.ACTION_UP ->{
                val rectf = RectF()
                path.computeBounds(rectf, true)
                val region = Region()
                region.setPath(
                    path,
                    Region(
                        rectf.left.toInt(),
                        rectf.top.toInt(),
                        rectf.right.toInt(),
                        rectf.bottom.toInt()
                    )
                )
                if (region.contains(event.x.toInt(), event.y.toInt())) {
                    if (!isAnimaling) {
                        startAnimation()
                    }
                }
                return true
            }
            MotionEvent.ACTION_DOWN -> return true
        }
        return super.onTouchEvent(event)

    }

    /**
     * 动画
     */
    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    private fun startAnimation() {
        val valueAnimator = ValueAnimator.ofFloat(0f, 45f)
        valueAnimator.addUpdateListener { animation ->
            run {
                rotate = (if (isOpen) 45 else 0) + animation.animatedValue as Float
                val scale = animation.animatedValue as Float / 45

                calculatePath(if (isOpen) 1 - scale else scale)
                invalidate()
            }
        }
        valueAnimator.addListener(object : Animator.AnimatorListener {
            override fun onAnimationRepeat(animation: Animator?) {
            }

            override fun onAnimationEnd(animation: Animator?) {
                isAnimaling = false
                isOpen = !isOpen
            }

            override fun onAnimationCancel(animation: Animator?) {
            }

            override fun onAnimationStart(animation: Animator?) {
                isAnimaling = true
            }

        })
        valueAnimator.duration = 1000
        valueAnimator.start()
    }
}